{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Getting Started with Loading 3D Annotations\n",
    "\n",
    "3D samples may contain any type and number of custom fields, including 3D detections and 3D polylines, which are natively visualizable by the [App’s 3D visualizer](https://docs.voxel51.com/user_guide/app.html#using-the-3d-visualizer).\n",
    "\n",
    "Because 3D annotations are stored in dedicated fields of datasets rather than being embedded in FO3D files, they can be queried and filtered via dataset views and in the App just like other primitive/label fields. It looks like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import fiftyone as fo\n",
    "\n",
    "scene = fo.Scene()\n",
    "scene.add(fo.GltfMesh(\"mesh\", \"mesh.gltf\"))\n",
    "scene.write(\"/path/to/scene.fo3d\")\n",
    "\n",
    "detection = fo.Detection(\n",
    "    label=\"vehicle\",\n",
    "    location=[0.47, 1.49, 69.44],\n",
    "    dimensions=[2.85, 2.63, 12.34],\n",
    "    rotation=[0, -1.56, 0],\n",
    ")\n",
    "\n",
    "sample = fo.Sample(\n",
    "    filepath=\"/path/to/scene.fo3d\",\n",
    "    ground_truth=fo.Detections(detections=[detection]),\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's break down the label a little bit more, diving into just exactly what `location`, `dimensions`, and `rotation` entail:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import fiftyone as fo\n",
    "\n",
    "# Object label\n",
    "label = \"vehicle\"\n",
    "\n",
    "# Object center `[x, y, z]` in scene coordinates\n",
    "location = [0.47, 1.49, 69.44]\n",
    "\n",
    "# Object dimensions `[x, y, z]` in scene units\n",
    "dimensions = [2.85, 2.63, 12.34]\n",
    "\n",
    "# Object rotation `[x, y, z]` around its center, in `[-pi, pi]`\n",
    "rotation = [0, -1.56, 0]\n",
    "\n",
    "# A 3D object detection\n",
    "detection = fo.Detection(\n",
    "    label=label,\n",
    "    location=location,\n",
    "    dimensions=dimensions,\n",
    "    rotation=rotation,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note here that scene coordinates are starting from `[0,0,0]` which almost always is the ego, or the location of where the sensor started. It does not map from any known global coordinates. \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3D Polylines\n",
    "3D Polylines work much the same as the detection do! They are stored as a decdicated field on your dataset and needs the arguments `label` and `points3d`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Object label\n",
    "label = \"lane\"\n",
    "\n",
    "# A list of lists of `[x, y, z]` points in scene coordinates describing\n",
    "# the vertices of each shape in the polyline\n",
    "points3d = [[[-5, -99, -2], [-8, 99, -2]], [[4, -99, -2], [1, 99, -2]]]\n",
    "\n",
    "# A set of semantically related 3D polylines\n",
    "polyline = fo.Polyline(label=label, points3d=points3d)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Another note, notice how for 3D you dont use `Detection3D` or `Polyline3D` classes from FiftyOne. The label classes `Detection` and `Polyline` will automatically adjust given 2D or 3D inputs!"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
